
#include <dev.h>
#include "i2c.h"

/* ------------------------------------------------------------------------- */

static i2c_dev_t *i2c_dev_table[I2C_DEV_NUM];

static const i2c_dev_t * fastcall addressing_device(uint16 addr);

/* ------------------------------------------------------------------------- */

void fastcall i2c_init(void)
{
	i2c_dev_table[I2C_DEV_MCU] = get_mcu_device();
	i2c_dev_table[I2C_DEV_HDTV] = get_hdtv_device();
}

void fastcall i2c_device_read(uint16 addr, uint8 cmd, void *buf, size_t size)
{
	size_t len;
	uint8 *ptr = buf;
	const i2c_dev_t *dev;

	memset(buf, 0xff, size);

	while (size > 0) {

		dev = addressing_device(addr);

		if (!dev) {
			assert(0);
			len = 1;
		} else {
			len = dev->read(cmd, ptr, size);
#ifndef NDEBUG
			switch (len)
			{
			case 1:
				write_log("[%s] read : %04Xh = %02Xh", dev->name, cmd, *ptr);
				break;
			case 2:
				write_log("[%s] read : %04Xh = %04Xh", dev->name, cmd, *(uint16 *)ptr);
				break;
			case 4:
				write_log("[%s] read : %04Xh = %08Xh", dev->name, cmd, *(uint32 *)ptr);
				break;
			default:
				assert(0);
				break;
			}
#endif
		}

		size -= len;
		ptr += len;
	}
}

void fastcall i2c_device_write(uint16 addr, uint8 cmd, const void *buf, size_t size)
{
	size_t len;
	const uint8 *ptr = buf;
	const i2c_dev_t *dev;

	while (size > 0) {

		dev = addressing_device(addr);

		if (!dev) {
			assert(0);
			len = 1;
		} else {
			len = dev->write(cmd, ptr, size);
#ifndef NDEBUG
			switch (len)
			{
			case 1:
				write_log("[%s] write : %04Xh = %02Xh", dev->name, cmd, *ptr);
				break;
			case 2:
				write_log("[%s] write : %04Xh = %04Xh", dev->name, cmd, *(uint16 *)ptr);
				break;
			case 4:
				write_log("[%s] write : %04Xh = %08Xh", dev->name, cmd, *(uint32 *)ptr);
				break;
			default:
				assert(0);
				break;
			}
#endif
		}

		size -= len;
		ptr += len;
	}
}

/* ------------------------------------------------------------------------- */

static const i2c_dev_t * fastcall addressing_device(uint16 addr)
{
	switch (addr) {
	case I2C_MCU_ADDR:
		return i2c_dev_table[I2C_DEV_MCU];
	case I2C_HDTV_ADDR:
		return i2c_dev_table[I2C_DEV_HDTV];
	case I2C_TSNS_ADDR:
		return i2c_dev_table[I2C_DEV_TSNS];
	case I2C_EEPROM_ADDR:
		return i2c_dev_table[I2C_DEV_EEPROM];
	default:
		assert(0);
		break;
	}

	return NULL;
}

/* ------------------------------------------------------------------------- */
